package com.ap.core.bulkupload.provider.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ap.core.bulkupload.handler.BulkUploadHandler;
import com.ap.core.bulkupload.info.BulkUploadBaseInfo;
import com.ap.core.bulkupload.info.BulkUploadMerchantResponseInfo;
import com.ap.core.bulkupload.provider.BulkFileUploadServiceProvider;
import com.ap.core.bulkupload.service.BusinessRuleValidationService;
import com.ap.core.bulkupload.service.SchemaValidationService;
import com.ap.core.bulkupload.types.BulkFileUploadEnum;
import com.ap.core.bulkupload.types.BulkUploadInfoBuilderType;
import com.ap.core.bulkupload.util.XMLWriterUtil;
import com.ap.core.bulkupload.validation.info.ValidationInfo;
import com.ap.core.bulkupload.validation.info.ValidationResult;
import com.ap.core.exception.APCoreException;


/**
 * The Class ServiceDelegaterUtil.
 */
public class BulkFileUploadServiceProviderImpl implements BulkFileUploadServiceProvider {

	/** The log. */
	private static final Logger log = LoggerFactory.getLogger(BulkFileUploadServiceProviderImpl.class);

	/** The bulk validation service. */
	private BusinessRuleValidationService businessRuleValidationService;

	/** The bulk schema validation service. */
	private SchemaValidationService schemaValidationService;

	/** The bulk upload handler. */
	private BulkUploadHandler bulkUploadHandler;	

	/* (non-Javadoc)
	 * @see com.ap.core.bulkupload.provider.BulkFileUploadServiceProvider#process(com.ap.core.bulkupload.types.BulkFileUploadEnum)
	 */
	@Override
	public String process(BulkFileUploadEnum bulkFileUploadEnum, String xmlFile) throws APCoreException {
		String outputFilePath = "";
		InputStream inputStream = null;
		try {			
			log.info("Entering ServiceDelegaterUtil.Process Method");						

			/* Validating Xml Schema */
			validateSchema(bulkFileUploadEnum, xmlFile);
			log.info("Bulkupload scheme validation is completed for ["+bulkFileUploadEnum.name()+"]");
			
			/* Business Rule Validation */
			inputStream = new FileInputStream(xmlFile);
			BulkUploadBaseInfo baseInfo = bulkUploadHandler.populateInfo(bulkFileUploadEnum, inputStream, BulkUploadInfoBuilderType.VALIDATION);
			validateBusinessRules(baseInfo, bulkFileUploadEnum);
			log.info("Bulkupload business rule validation is completed for ["+bulkFileUploadEnum.name()+"]");

			/* Register Merchant */
			inputStream = new FileInputStream(xmlFile);
			BulkUploadMerchantResponseInfo merchantResponseInfo = (BulkUploadMerchantResponseInfo)bulkUploadHandler.populateInfo(bulkFileUploadEnum, inputStream, BulkUploadInfoBuilderType.REGISTER);
			log.info("Bulkupload Merchant registration is completed");
			
			/* Writing into the file */
			if(null != merchantResponseInfo && null != merchantResponseInfo.getMerchantRegBulkUploadResponse()) {
				File file = XMLWriterUtil.getInstance().writeToXmlFile(merchantResponseInfo.getMerchantRegBulkUploadResponse(), xmlFile);
				log.info("Bulkupload response writing into a file completed for ["+xmlFile+"]");
				/* archive the file */
				XMLWriterUtil.getInstance().archiveFile(xmlFile, merchantResponseInfo.getMerchantRegBulkUploadResponse().getDistributorId().getValue());
				log.info("File archiving completed for ["+xmlFile+"]");
				outputFilePath = file.getAbsolutePath();
			}

			log.info("BulkFileUpload Processing is completed for ["+bulkFileUploadEnum.name()+"]");
			return outputFilePath;
		}catch(APCoreException e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw e;
 		} catch (Exception e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw new APCoreException(e);
		}
	}
	
	/**
	 * Validate schema.
	 *
	 * @param bulkFileUploadEnum the bulk file upload enum
	 * @param xmlFile the xml file
	 * @throws APCoreException the aP core exception
	 */
	private void validateSchema(BulkFileUploadEnum bulkFileUploadEnum, String xmlFile) throws APCoreException {
		ValidationResult validationResult;

		try {
			InputStream inputStream = new FileInputStream(xmlFile);
			validationResult = schemaValidationService.validate(bulkFileUploadEnum, inputStream); 
			if (validationResult != null && validationResult.getFailedRulesInfo().size() > 0) {
				ValidationInfo validationInfo = validationResult.getFailedRulesInfo().get(0);
				log.error("Bulk File Upload Schema Validation Failed [ErrorCode :" + validationInfo.getInternalBusinessErrorCode() + " desc :"+validationInfo.getRuleDescription()+"]");
				throw new APCoreException("Bulk File Upload Schema Validation Failed [ErrorCode :" + validationInfo.getInternalBusinessErrorCode() + " desc :"+validationInfo.getRuleDescription()+"]");
			}			
		}  catch(APCoreException e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw e;
 		} catch (Exception e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw new APCoreException(e);
		}

	}	

	/**
	 * Check for bulk validation business rules.
	 *
	 * @param baseInfo the base info
	 * @param bulkFileUploadEnum the bulk file upload enum
	 */
	private void validateBusinessRules(BulkUploadBaseInfo baseInfo, BulkFileUploadEnum bulkFileUploadEnum) throws APCoreException {

		// Call bulk Validation business Rules
		ValidationResult validationResult;
		try {
			validationResult = businessRuleValidationService.validate(
					baseInfo, bulkFileUploadEnum);
			if (!validationResult.isValid()) {
				log.error("Following Business Rule Validaions Failed");
				String errorMsg = "";
				for (ValidationInfo validationIn : validationResult
						.getFailedRulesInfo()) {
					log.error("Business Rule" + validationIn.getInternalBusinessErrorCode());
					//log.error("Business Rule" + validationIn.getRuleId());
					log.error("Business Rule" + validationIn.getRuleDescription());
					errorMsg = errorMsg + "Error code ["+validationIn.getInternalBusinessErrorCode()+"]  Desc ["+validationIn.getRuleDescription()+"]";
				}
				throw new APCoreException("Rule Validaions Failed with "+errorMsg);
			}			
		}  catch(APCoreException e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw e;
 		} catch (Exception e) {
			log.error("Error while Processing BulkFileUpload ["+bulkFileUploadEnum.name()+"] and Error ["+e.getMessage()+"]");
			throw new APCoreException(e);
		}
	}

	/**
	 * Sets the bulk upload handler.
	 *
	 * @param bulkUploadHandler the bulkUploadHandler to set
	 */
	public void setBulkUploadHandler(BulkUploadHandler bulkUploadHandler) {
		this.bulkUploadHandler = bulkUploadHandler;
	}

	/* (non-Javadoc)
	 * @see com.ap.core.bulkupload.provider.BulkFileUploadServiceProvider#setBusinessRuleValidationService(com.ap.core.bulkupload.service.BusinessRuleValidationService)
	 */
	@Override
	public void setBusinessRuleValidationService(
			BusinessRuleValidationService businessRuleValidationService) {
	this.businessRuleValidationService = businessRuleValidationService;
	}

	/* (non-Javadoc)
	 * @see com.ap.core.bulkupload.provider.BulkFileUploadServiceProvider#setSchemaValidationService(com.ap.core.bulkupload.service.SchemaValidationService)
	 */
	@Override
	public void setSchemaValidationService(
			SchemaValidationService schemaValidationService) {
	this.schemaValidationService = schemaValidationService;
	}	
}
